package com.dragon.refect.classload;

/**
 * 当前类加载器(Current Classloader)
 *
 * 每个类都会使用自己的类加载器(即加载自身的类加载器)来加载其他类(指的都是所依赖的类)
 * 如果ClassX引用了ClassY,那么ClassX的类加载器就会去加载ClassY(前提是ClassY尚未被加载)
 *
 * 线程上下文类加载器(Context Classloader)
 *
 * 线程上下文类加载器是从JDK1.2开始引入的，类Thread中的getContextClassLoader()与setContextClassLoader(Classloader c1)
 * 分别是用来获取和设置上下文类加载器的
 *
 * 如果没有通过setContextClassLoader(ClassLoader c1)进行设置的话，线程将继承器父线程的上下文类加载器。
 * Java应用运行时的初始化线程的上下文类加载器是系统类加载器。在线程中运行的代码可以通过该类加载器来加载类与资源
 *
 * 线程上下文类加载器的重要性:
 * SPI(Service Provide Interface)
 *
 * 父ClassLoader可以使用当前线程Thread.currentThread().getContextClassLoader()所指定的classloader来加载的的类。
 * 这就改变了父Classloader不能使用子ClassLoader或是其他没有直接父子关系的classloader加载的类情况。即改变了双亲委托模型。
 *
 * 线程上下文类加载器就是当前线程的Current Classloader
 *
 * 在双亲委托模型下，类加载是由下至上的，即下层的类加载器会委托下层进行加载。但是对于SPI来说，有些接口是Java核心库所提供的
 * 而Java核心库是由启动类加载器所洗载的，而这些接口的实现却是来自于不同的jar包(厂商提供),Java的启动类加载器是不会加载其他来源的Jar包，
 * 这样传统的双亲委托模型则无法满足SPI的要求。而通过给当前线程设置上下文类加载器，就可以由设置的上下文类加载器来实现对于接口实现类的加载。
 *
 * @author dragon
 * @since 2019/11/25
 */
public class MyTest13 {

    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getContextClassLoader());
        System.out.println(Thread.class.getClassLoader());
    }
}
